From a8c6ae6085f72219548141a0d833cdc729e26c67 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 20 Mar 2020 23:54:39 -0400 Subject: [PATCH] texttag: Support overline and hyphenation control Add support for recently added Pango attributes for overlines and hyphenation control. The new properties of GtkTextTag are overline, overline-rgba, allow-breaks, show-spaces and insert-hyphens. --- gtk/gtktextattributes.c | 38 +++++++- gtk/gtktextattributes.h | 6 ++ gtk/gtktexttag.c | 194 ++++++++++++++++++++++++++++++++++++++++ gtk/gtktexttagprivate.h | 5 ++ 4 files changed, 242 insertions(+), 1 deletion(-) diff --git a/gtk/gtktextattributes.c b/gtk/gtktextattributes.c index e6561cbe9b..47c73232a3 100644 --- a/gtk/gtktextattributes.c +++ b/gtk/gtktextattributes.c @@ -140,6 +140,9 @@ gtk_text_attributes_copy_values (GtkTextAttributes *src, if (dest->appearance.underline_rgba) gdk_rgba_free (dest->appearance.underline_rgba); + if (dest->appearance.overline_rgba) + gdk_rgba_free (dest->appearance.overline_rgba); + if (dest->appearance.strikethrough_rgba) gdk_rgba_free (dest->appearance.strikethrough_rgba); @@ -171,6 +174,9 @@ gtk_text_attributes_copy_values (GtkTextAttributes *src, if (src->appearance.underline_rgba) dest->appearance.underline_rgba = gdk_rgba_copy (src->appearance.underline_rgba); + if (src->appearance.overline_rgba) + dest->appearance.overline_rgba = gdk_rgba_copy (src->appearance.overline_rgba); + if (src->appearance.strikethrough_rgba) dest->appearance.strikethrough_rgba = gdk_rgba_copy (src->appearance.strikethrough_rgba); @@ -233,6 +239,9 @@ gtk_text_attributes_unref (GtkTextAttributes *values) if (values->appearance.underline_rgba) gdk_rgba_free (values->appearance.underline_rgba); + if (values->appearance.overline_rgba) + gdk_rgba_free (values->appearance.underline_rgba); + if (values->appearance.strikethrough_rgba) gdk_rgba_free (values->appearance.strikethrough_rgba); @@ -300,6 +309,18 @@ _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest, dest->appearance.underline_rgba = gdk_rgba_copy (vals->appearance.underline_rgba); } + if (tag->priv->overline_rgba_set) + { + if (dest->appearance.overline_rgba) + { + gdk_rgba_free (dest->appearance.overline_rgba); + dest->appearance.overline_rgba = NULL; + } + + if (vals->appearance.overline_rgba) + dest->appearance.overline_rgba = gdk_rgba_copy (vals->appearance.overline_rgba); + } + if (tag->priv->strikethrough_rgba_set) { if (dest->appearance.strikethrough_rgba) @@ -386,6 +407,9 @@ _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest, if (tag->priv->underline_set) dest->appearance.underline = vals->appearance.underline; + if (tag->priv->overline_set) + dest->appearance.overline = vals->appearance.overline; + if (tag->priv->strikethrough_set) dest->appearance.strikethrough = vals->appearance.strikethrough; @@ -410,6 +434,15 @@ _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest, if (tag->priv->font_features_set) dest->font_features = g_strdup (vals->font_features); + if (tag->priv->allow_breaks_set) + dest->no_breaks = vals->no_breaks; + + if (tag->priv->show_spaces_set) + dest->show_spaces = vals->show_spaces; + + if (tag->priv->insert_hyphens_set) + dest->no_hyphens = vals->no_hyphens; + ++n; } @@ -435,6 +468,7 @@ _gtk_text_tag_affects_size (GtkTextTag *tag) priv->pixels_inside_wrap_set || priv->tabs_set || priv->underline_set || + priv->overline_set || priv->wrap_mode_set || priv->invisible_set || priv->font_features_set || @@ -454,5 +488,7 @@ _gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag) priv->pg_bg_color_set || priv->fallback_set || priv->underline_rgba_set || - priv->strikethrough_rgba_set; + priv->overline_rgba_set || + priv->strikethrough_rgba_set || + priv->show_spaces_set; } diff --git a/gtk/gtktextattributes.h b/gtk/gtktextattributes.h index 8dedeac440..f6332c0dc7 100644 --- a/gtk/gtktextattributes.h +++ b/gtk/gtktextattributes.h @@ -87,12 +87,14 @@ struct _GtkTextAppearance GdkRGBA *bg_rgba; GdkRGBA *fg_rgba; GdkRGBA *underline_rgba; + GdkRGBA *overline_rgba; GdkRGBA *strikethrough_rgba; /* super/subscript rise, can be negative */ gint rise; guint underline : 4; /* PangoUnderline */ + guint overline : 2; /* PangoOverline */ guint strikethrough : 1; /* Whether to use background-related values; this is irrelevant for @@ -170,6 +172,10 @@ struct _GtkTextAttributes guint bg_full_height : 1; guint editable : 1; guint no_fallback: 1; + guint no_breaks : 1; + guint show_spaces : 3; /* PangoShowFlags */ + gint no_hyphens : 1; + GdkRGBA *pg_bg_rgba; diff --git a/gtk/gtktexttag.c b/gtk/gtktexttag.c index d04606f463..7465465eb9 100644 --- a/gtk/gtktexttag.c +++ b/gtk/gtktexttag.c @@ -116,7 +116,9 @@ enum { PROP_STRIKETHROUGH_RGBA, PROP_RIGHT_MARGIN, PROP_UNDERLINE, + PROP_OVERLINE, PROP_UNDERLINE_RGBA, + PROP_OVERLINE_RGBA, PROP_RISE, PROP_BACKGROUND_FULL_HEIGHT, PROP_LANGUAGE, @@ -127,6 +129,9 @@ enum { PROP_FALLBACK, PROP_LETTER_SPACING, PROP_FONT_FEATURES, + PROP_ALLOW_BREAKS, + PROP_SHOW_SPACES, + PROP_INSERT_HYPHENS, /* Behavior args */ PROP_ACCUMULATIVE_MARGIN, @@ -153,7 +158,9 @@ enum { PROP_STRIKETHROUGH_RGBA_SET, PROP_RIGHT_MARGIN_SET, PROP_UNDERLINE_SET, + PROP_OVERLINE_SET, PROP_UNDERLINE_RGBA_SET, + PROP_OVERLINE_RGBA_SET, PROP_RISE_SET, PROP_BACKGROUND_FULL_HEIGHT_SET, PROP_LANGUAGE_SET, @@ -163,6 +170,9 @@ enum { PROP_FALLBACK_SET, PROP_LETTER_SPACING_SET, PROP_FONT_FEATURES_SET, + PROP_ALLOW_BREAKS_SET, + PROP_SHOW_SPACES_SET, + PROP_INSERT_HYPHENS_SET, LAST_ARG }; @@ -482,6 +492,15 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) PANGO_UNDERLINE_NONE, GTK_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_OVERLINE, + g_param_spec_enum ("overline", + P_("Overline"), + P_("Style of overline for this text"), + PANGO_TYPE_OVERLINE, + PANGO_OVERLINE_NONE, + GTK_PARAM_READWRITE)); + /** * GtkTextTag:underline-rgba: * @@ -500,6 +519,14 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) GDK_TYPE_RGBA, GTK_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_OVERLINE_RGBA, + g_param_spec_boxed ("overline-rgba", + P_("Overline RGBA"), + P_("Color of overline for this text"), + GDK_TYPE_RGBA, + GTK_PARAM_READWRITE)); + /** * GtkTextTag:strikethrough-rgba: * @@ -617,6 +644,31 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) NULL, GTK_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_ALLOW_BREAKS, + g_param_spec_boolean ("allow-breaks", + P_("Allow Breaks"), + P_("Whether breaks are allowed."), + TRUE, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_SHOW_SPACES, + g_param_spec_flags ("show-spaces", + P_("Show spaces"), + P_("How to render invisible characters."), + PANGO_TYPE_SHOW_FLAGS, + PANGO_SHOW_NONE, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_INSERT_HYPHENS, + g_param_spec_boolean ("insert-hyphens", + P_("Insert hyphens"), + P_("Whether to insert hyphens at breaks."), + TRUE, + GTK_PARAM_READWRITE)); + /** * GtkTextTag:accumulative-margin: * @@ -726,6 +778,10 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) P_("Underline set"), P_("Whether this tag affects underlining")); + ADD_SET_PROP ("overline-set", PROP_OVERLINE_SET, + P_("Overline set"), + P_("Whether this tag affects overlining")); + /** * GtkTextTag:underline-rgba-set: * @@ -735,6 +791,10 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) P_("Underline RGBA set"), P_("Whether this tag affects underlining color")); + ADD_SET_PROP ("overline-rgba-set", PROP_OVERLINE_RGBA_SET, + P_("Overline RGBA set"), + P_("Whether this tag affects overlining color")); + /** * GtkTextTag:strikethrough-rgba-set: * @@ -771,6 +831,18 @@ gtk_text_tag_class_init (GtkTextTagClass *klass) ADD_SET_PROP ("font-features-set", PROP_FONT_FEATURES_SET, P_("Font features set"), P_("Whether this tag affects font features")); + + ADD_SET_PROP ("allow-breaks-set", PROP_ALLOW_BREAKS_SET, + P_("Allow breaks set"), + P_("Whether this tag affects line breaks")); + + ADD_SET_PROP ("show-spaces-set", PROP_SHOW_SPACES_SET, + P_("Show spaces set"), + P_("Whether this tag affects rendering of invisible characters")); + + ADD_SET_PROP ("insert-hyphens-set", PROP_INSERT_HYPHENS_SET, + P_("Insert hyphens set"), + P_("Whether this tag affects insertion of hyphens")); } static void @@ -849,6 +921,36 @@ set_underline_rgba (GtkTextTag *tag, } } +static void +set_overline_rgba (GtkTextTag *tag, + const GdkRGBA *rgba) +{ + GtkTextTagPrivate *priv = tag->priv; + + if (priv->values->appearance.overline_rgba) + gdk_rgba_free (priv->values->appearance.overline_rgba); + priv->values->appearance.overline_rgba = NULL; + + if (rgba) + { + priv->values->appearance.overline_rgba = gdk_rgba_copy (rgba); + + if (!priv->overline_rgba_set) + { + priv->overline_rgba_set = TRUE; + g_object_notify (G_OBJECT (tag), "overline-rgba-set"); + } + } + else + { + if (priv->overline_rgba_set) + { + priv->overline_rgba_set = FALSE; + g_object_notify (G_OBJECT (tag), "overline-rgba-set"); + } + } +} + static void set_strikethrough_rgba (GtkTextTag *tag, const GdkRGBA *rgba) @@ -1366,6 +1468,12 @@ gtk_text_tag_set_property (GObject *object, g_object_notify (object, "underline-set"); break; + case PROP_OVERLINE: + priv->overline_set = TRUE; + priv->values->appearance.overline = g_value_get_enum (value); + g_object_notify (object, "overline-set"); + break; + case PROP_UNDERLINE_RGBA: { GdkRGBA *color = g_value_get_boxed (value); @@ -1373,6 +1481,13 @@ gtk_text_tag_set_property (GObject *object, } break; + case PROP_OVERLINE_RGBA: + { + GdkRGBA *color = g_value_get_boxed (value); + set_overline_rgba (text_tag, color); + } + break; + case PROP_RISE: priv->rise_set = TRUE; priv->values->appearance.rise = g_value_get_int (value); @@ -1453,6 +1568,24 @@ gtk_text_tag_set_property (GObject *object, g_object_notify (object, "font-features-set"); break; + case PROP_ALLOW_BREAKS: + priv->allow_breaks_set = TRUE; + priv->values->no_breaks = !g_value_get_boolean (value); + g_object_notify (object, "allow-breaks-set"); + break; + + case PROP_SHOW_SPACES: + priv->show_spaces_set = TRUE; + priv->values->show_spaces = g_value_get_flags (value); + g_object_notify (object, "show-spaces-set"); + break; + + case PROP_INSERT_HYPHENS: + priv->insert_hyphens_set = TRUE; + priv->values->no_hyphens = !g_value_get_boolean (value); + g_object_notify (object, "insert-hyphens-set"); + break; + case PROP_ACCUMULATIVE_MARGIN: priv->accumulative_margin = g_value_get_boolean (value); g_object_notify (object, "accumulative-margin"); @@ -1553,10 +1686,18 @@ gtk_text_tag_set_property (GObject *object, priv->underline_set = g_value_get_boolean (value); break; + case PROP_OVERLINE_SET: + priv->overline_set = g_value_get_boolean (value); + break; + case PROP_UNDERLINE_RGBA_SET: priv->underline_rgba_set = g_value_get_boolean (value); break; + case PROP_OVERLINE_RGBA_SET: + priv->overline_rgba_set = g_value_get_boolean (value); + break; + case PROP_RISE_SET: priv->rise_set = g_value_get_boolean (value); size_changed = TRUE; @@ -1597,6 +1738,18 @@ gtk_text_tag_set_property (GObject *object, priv->font_features_set = g_value_get_boolean (value); break; + case PROP_ALLOW_BREAKS_SET: + priv->allow_breaks_set = g_value_get_boolean (value); + break; + + case PROP_SHOW_SPACES_SET: + priv->show_spaces_set = g_value_get_boolean (value); + break; + + case PROP_INSERT_HYPHENS_SET: + priv->insert_hyphens_set = g_value_get_boolean (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1741,11 +1894,20 @@ gtk_text_tag_get_property (GObject *object, g_value_set_enum (value, priv->values->appearance.underline); break; + case PROP_OVERLINE: + g_value_set_enum (value, priv->values->appearance.overline); + break; + case PROP_UNDERLINE_RGBA: if (priv->underline_rgba_set) g_value_set_boxed (value, priv->values->appearance.underline_rgba); break; + case PROP_OVERLINE_RGBA: + if (priv->overline_rgba_set) + g_value_set_boxed (value, priv->values->appearance.overline_rgba); + break; + case PROP_RISE: g_value_set_int (value, priv->values->appearance.rise); break; @@ -1784,6 +1946,18 @@ gtk_text_tag_get_property (GObject *object, g_value_set_string (value, priv->values->font_features); break; + case PROP_ALLOW_BREAKS: + g_value_set_boolean (value, !priv->values->no_breaks); + break; + + case PROP_SHOW_SPACES: + g_value_set_flags (value, priv->values->show_spaces); + break; + + case PROP_INSERT_HYPHENS: + g_value_set_boolean (value, !priv->values->no_hyphens); + break; + case PROP_ACCUMULATIVE_MARGIN: g_value_set_boolean (value, priv->accumulative_margin); break; @@ -1862,10 +2036,18 @@ gtk_text_tag_get_property (GObject *object, g_value_set_boolean (value, priv->underline_set); break; + case PROP_OVERLINE_SET: + g_value_set_boolean (value, priv->overline_set); + break; + case PROP_UNDERLINE_RGBA_SET: g_value_set_boolean (value, priv->underline_rgba_set); break; + case PROP_OVERLINE_RGBA_SET: + g_value_set_boolean (value, priv->overline_rgba_set); + break; + case PROP_RISE_SET: g_value_set_boolean (value, priv->rise_set); break; @@ -1902,6 +2084,18 @@ gtk_text_tag_get_property (GObject *object, g_value_set_boolean (value, priv->font_features_set); break; + case PROP_ALLOW_BREAKS_SET: + g_value_set_boolean (value, priv->allow_breaks_set); + break; + + case PROP_SHOW_SPACES_SET: + g_value_set_boolean (value, priv->show_spaces_set); + break; + + case PROP_INSERT_HYPHENS_SET: + g_value_set_boolean (value, priv->insert_hyphens_set); + break; + case PROP_BACKGROUND: case PROP_FOREGROUND: case PROP_PARAGRAPH_BACKGROUND: diff --git a/gtk/gtktexttagprivate.h b/gtk/gtktexttagprivate.h index 75f448d702..4fe63d4249 100644 --- a/gtk/gtktexttagprivate.h +++ b/gtk/gtktexttagprivate.h @@ -59,6 +59,7 @@ struct _GtkTextTagPrivate guint bg_color_set : 1; guint fg_color_set : 1; guint underline_rgba_set : 1; + guint overline_rgba_set : 1; guint strikethrough_rgba_set : 1; guint scale_set : 1; guint justification_set : 1; @@ -72,6 +73,7 @@ struct _GtkTextTagPrivate guint pixels_inside_wrap_set : 1; guint tabs_set : 1; guint underline_set : 1; + guint overline_set : 1; guint wrap_mode_set : 1; guint bg_full_height_set : 1; guint invisible_set : 1; @@ -81,6 +83,9 @@ struct _GtkTextTagPrivate guint fallback_set : 1; guint letter_spacing_set : 1; guint font_features_set : 1; + guint allow_breaks_set : 1; + guint show_spaces_set : 1; + guint insert_hyphens_set : 1; /* Whether these margins accumulate or override */ guint accumulative_margin : 1; -- 2.30.2